package com.tfleo.mealssenger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import com.github.ignition.core.widgets.RemoteImageView;
import com.tfleo.mealssenger.adapter.NewsListAdapter;
import com.tfleo.mealssenger.object.News;
import com.tfleo.mealssenger.object.User;
import com.tfleo.mealssenger.service.ChatService;
import com.tfleo.mealssenger.utility.DataFetcher;
import com.tfleo.mealssenger.utility.NetworkTools;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.Secure;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewSwitcher;

public class UserActivity extends Activity {
	private static final int ERROR = 0;
	public static final int MYSELF = 1;
	public static final int NOT_FRIEND = 2;
	public static final int IS_FRIEND = 3;
	private static final int REQUEST_SENT = 14;
	private static final int APPROVAL_NEEDED = 15;

	public static final String WHO = "who";
	private static final String TAG = "UserActivity";

	private ViewSwitcher vSwitcher;
	private TextView vName;
	private TextView vOnlineStatus;
	private TextView vLastCheckinLabel;
	private TextView vLastCheckin;
	private Button vAddFriendButton;
	private Button vWantedlistButton;
	private Button vChatButton;
	private Button vFriendslistButton;
	private RemoteImageView vImage;
	private ListView vNewsList;

	private ArrayList<News> mNewsList;
	private NewsListAdapter mNewsAdapter;
	private Context mContext;
	private LayoutInflater mInflater;
	private SharedPreferences mSharedPref;

	private int mWho = ERROR;
	private User mUser;
	private boolean isOnline = false;
	private String mAuth;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.user_layout);
		mContext = this;
		mInflater = (LayoutInflater) getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
		mSharedPref = getSharedPreferences(Main.USER_DATA, MODE_PRIVATE);
		mAuth = Secure.getString(this.getContentResolver(), Secure.ANDROID_ID); //for authentication

		Bundle extras = getIntent().getExtras();
		if(extras != null) {
			mWho = extras.getInt(WHO, ERROR);
			mUser = new User(extras.getInt("id"),
					extras.getString("name"),
					extras.getString("imageUrl"),
					extras.getInt("lastCheckin"),
					extras.getInt("placeId"),
					extras.getString("placeName")
					);
		} else {
			Toast.makeText(mContext, "Error: Bundle is null!", Toast.LENGTH_SHORT).show();
			finish();
		}

		if(mUser.id <= 0 || mWho == ERROR) {
			Toast.makeText(mContext, "Error: Invalid id!", Toast.LENGTH_SHORT).show();
			finish();
		}

		vName = (TextView) findViewById(R.id.name);
		vOnlineStatus = (TextView) findViewById(R.id.online_status);
		vLastCheckin = (TextView) findViewById(R.id.last_checkin);
		vLastCheckinLabel = (TextView) findViewById(R.id.last_checkin_label);
		vImage = (RemoteImageView) findViewById(R.id.image);
		vSwitcher = (ViewSwitcher) findViewById(R.id.switcher);
		vNewsList = (ListView) findViewById(R.id.news_list);
		vAddFriendButton = (Button) findViewById(R.id.add_friend_btn);

		FetchUserTask task = new FetchUserTask();
		switch(mWho) {
		case NOT_FRIEND: //not sure is friend or not
			//Retrieve data
			task.execute(new Integer[] {mSharedPref.getInt(Main.USER_ID, 0), mUser.id, 0});
			break;
		case IS_FRIEND:
			//Check if retrieval needed
			if(mUser.name == null || mUser.imageUrl == null) {
				task.execute(new Integer[] {mSharedPref.getInt(Main.USER_ID, 0), mUser.id, 1});
			} else {
				registerReceiver(mChatStatusReceiver, new IntentFilter(ChatService.MEALSSENGER_CHATSTATUS));
				ChatService.actionGetStatus(getApplicationContext(), Integer.toString(mUser.id));

				FetchNewsTask newsTask = new FetchNewsTask();
				newsTask.execute(mSharedPref.getInt(Main.USER_ID, 0), mUser.id);
				setupView();
			}
			break;
		}
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if ((keyCode == KeyEvent.KEYCODE_BACK)) {
			finish();
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	public void onDestroy() {
		try {
			unregisterReceiver(mChatStatusReceiver);
		} catch(IllegalArgumentException e) {
			e.printStackTrace();
		}
		super.onDestroy();
	}

	public int isFriend(int myId, int otherId) {
		try {
			URL url = new URL(Main.SERVER_URL + "is_friend.php?from_user=" + myId + "&to_user=" + otherId);
			URLConnection conn = url.openConnection();
			BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

			String responseBody;
			if((responseBody = in.readLine()) != null) {
				JSONObject response = new JSONObject(responseBody);
				return response.getInt("result");
			} else {
				return 0;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return 0;
	}

	public boolean requestFriend(int myId, int otherId) {
		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(Main.SERVER_URL + "user/" + otherId + "/addfriend");

		if(!NetworkTools.isNetworkAvailable(mContext)) {
			Toast.makeText(getApplicationContext(),
					"Warning: Network is currently unavailable!", Toast.LENGTH_LONG).show();
			return false;
		}

		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("from_user", Integer.toString(myId)));
			//nameValuePairs.add(new BasicNameValuePair("to_user", Integer.toString(otherId)));
			nameValuePairs.add(new BasicNameValuePair("auth", mAuth));
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

			// Execute HTTP Post Request
			ResponseHandler<String> responseHandler = new BasicResponseHandler();
			String responseBody = httpclient.execute(httppost, responseHandler);
			JSONObject response = new JSONObject(responseBody);

			if(response.getInt("code") == 1) {
				ChatService.actionAddFriend(getApplicationContext(), Integer.toString(otherId));
				return true;
			} else {
				return false;
			}
		} catch(JSONException e){
			e.printStackTrace();
		} catch(IOException e) {
			e.printStackTrace();
		} catch(Exception e) {
			e.printStackTrace();
		}

		return false;
	}

	public boolean approveFriend(int myId, int otherId) {
		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(Main.SERVER_URL + "user/" + otherId + "/approvefriend");

		if(!NetworkTools.isNetworkAvailable(mContext)) {
			Toast.makeText(getApplicationContext(),
					"Warning: Network is currently unavailable!", Toast.LENGTH_LONG).show();
			return false;
		}

		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("from_user", Integer.toString(myId)));
			//nameValuePairs.add(new BasicNameValuePair("to_user", Integer.toString(otherId)));
			nameValuePairs.add(new BasicNameValuePair("auth", mAuth));
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

			// Execute HTTP Post Request
			ResponseHandler<String> responseHandler = new BasicResponseHandler();
			String responseBody = httpclient.execute(httppost, responseHandler);
			JSONObject response = new JSONObject(responseBody);

			if(response.getInt("code") == 1) {
				ChatService.actionApproveFriend(getApplicationContext(), Integer.toString(otherId));
				//ChatService.actionAddFriend(getApplicationContext(), mUser.name);
				return true;
			} else {
				return false;
			}
		} catch(JSONException e){
			e.printStackTrace();
		} catch(IOException e) {
			e.printStackTrace();
		} catch(Exception e) {
			e.printStackTrace();
		}

		return false;
	}

	private class FetchNewsTask extends AsyncTask<Integer, Void, Boolean> {
		private ProgressDialog mProgressDialog;

		@Override    
		protected void onPreExecute() {       
			super.onPreExecute();
			mProgressDialog = new ProgressDialog(mContext);
			mProgressDialog.setMessage("Loading...");
			mProgressDialog.setCancelable(false);
			mProgressDialog.setIndeterminate(true);
			mProgressDialog.show();      
		}

		@Override
		protected Boolean doInBackground(Integer... id) {
			int myId = id[0];
			int otherId = id[1];
			mNewsList = DataFetcher.fetchOwnNews(otherId, myId, mAuth);
			if(mNewsList == null) {
				return false;
			}
			return true;
		}

		@Override
		protected void onPostExecute(Boolean result) {
			if(result) {
				mNewsAdapter = new NewsListAdapter(mContext,
						R.layout.news_entry, R.id.name, mNewsList, mInflater);
				vNewsList = (ListView) findViewById(R.id.news_list);
				vNewsList.setAdapter(mNewsAdapter);
			} else {
				Toast.makeText(getApplicationContext(), "Error: Failed server request!", 
						Toast.LENGTH_SHORT).show();
			}
			mProgressDialog.dismiss();
		}

	}

	private class FetchUserTask extends AsyncTask<Integer, Void, Integer> {
		private ProgressDialog mProgressDialog;

		@Override    
		protected void onPreExecute() {       
			super.onPreExecute();
			mProgressDialog = new ProgressDialog(mContext);
			mProgressDialog.setMessage("Loading...");
			mProgressDialog.setCancelable(false);
			mProgressDialog.setIndeterminate(true);
			mProgressDialog.show();      
		}

		@Override
		protected Integer doInBackground(Integer... id) {
			int myId = id[0];
			int otherId = id[1];


			if(myId == otherId) {
				mUser = new User(myId, mSharedPref.getString(Main.USER_NAME, "Kirunavaara"), 
						mSharedPref.getString(Main.USER_IMAGE, Main.SERVER_URL + "img/user/0.jpg"), 
						mSharedPref.getInt(Main.LAST_CHECKIN_ID, 0), 
						mSharedPref.getInt(Main.LAST_CHECKIN_PLACEID, 0),
						mSharedPref.getString(Main.LAST_CHECKIN_PLACENAME, ""));
				mNewsList = DataFetcher.fetchOwnNews(myId, myId, mAuth);
				if(mNewsList == null) {
					return ERROR;
				}
				return MYSELF;
			}
			
			mUser = DataFetcher.fetchUser(otherId, myId, mAuth);

			if(id[2] == 1) { //definitely friend
				//mUser = DataFetcher.fetchUser(otherId, myId, mAuth);
				if(mUser == null) {
					return ERROR;
				} else {
					mNewsList = DataFetcher.fetchOwnNews(otherId, myId, mAuth);
					if(mNewsList == null) {
						return ERROR;
					}
					return IS_FRIEND;
				}
			}

			switch(isFriend(myId, otherId)) {
			case 0:
				//mUser = DataFetcher.fetchUser(otherId, myId, mAuth);
				return NOT_FRIEND;
			case 1:
				//mUser = DataFetcher.fetchUser(otherId);
				if(mUser == null) {
					return ERROR;
				} else {
					mNewsList = DataFetcher.fetchOwnNews(otherId, myId, mAuth);
					if(mNewsList == null) {
						return ERROR;
					}
					return IS_FRIEND;
				}
			case 2:
				//mUser = DataFetcher.fetchPublicUser(otherId);
				return REQUEST_SENT;
			case 3:
				//mUser = DataFetcher.fetchPublicUser(otherId);
				return APPROVAL_NEEDED;
			default:
				return ERROR;	
			}
		}

		@Override
		protected void onPostExecute(Integer result) {
			switch(result) {
			case NOT_FRIEND:
				vAddFriendButton.setVisibility(View.VISIBLE);
				vAddFriendButton.setOnClickListener(new OnClickListener() {
					public void onClick(View v) {
						RequestFriendTask task = new RequestFriendTask();
						task.execute(new Integer[] {mSharedPref.getInt(Main.USER_ID, 0), mUser.id});
					}
				});
				vName.setText(mUser.name);
				vImage.setImageUrl(mUser.imageUrl);
				vImage.loadImage();
				break;
			case IS_FRIEND:
				registerReceiver(mChatStatusReceiver, new IntentFilter(ChatService.MEALSSENGER_CHATSTATUS));
				ChatService.actionGetStatus(getApplicationContext(), Integer.toString(mUser.id));
			case MYSELF:
				mNewsAdapter = new NewsListAdapter(mContext,
						R.layout.news_entry, R.id.name, mNewsList, mInflater);
				vNewsList = (ListView) findViewById(R.id.news_list);
				vNewsList.setAdapter(mNewsAdapter);

				setupView();
				break;
			case REQUEST_SENT:
				vAddFriendButton.setVisibility(View.VISIBLE);
				vAddFriendButton.setText("Friend request sent");
				vAddFriendButton.setEnabled(false);
				vAddFriendButton.setBackgroundColor(Color.parseColor("#00000000"));
				vAddFriendButton.setTextColor(getResources().getColor(R.color.dark_brown));
				vName.setText(mUser.name);
				vImage.setImageUrl(mUser.imageUrl);
				vImage.loadImage();
				break;
			case APPROVAL_NEEDED:
				vAddFriendButton.setVisibility(View.VISIBLE);
				vAddFriendButton.setText("Approve request");
				vAddFriendButton.setOnClickListener(new OnClickListener() {
					public void onClick(View v) {
						ApproveFriendTask task = new ApproveFriendTask();
						task.execute(new Integer[] {mSharedPref.getInt(Main.USER_ID, 0), mUser.id});
					}
				});
				vName.setText(mUser.name);
				vImage.setImageUrl(mUser.imageUrl);
				vImage.loadImage();
				break;

			default:
				Toast.makeText(getApplicationContext(), "Error: Failed server request!", 
						Toast.LENGTH_SHORT).show();	
			}
			mProgressDialog.dismiss();
		}
	}

	private class RequestFriendTask extends AsyncTask<Integer, Void, Boolean> {

		@Override
		protected Boolean doInBackground(Integer... id) {
			int myId = id[0];
			int otherId = id[1];

			return requestFriend(myId, otherId);
		}

		@Override
		protected void onPostExecute(Boolean result) {
			if(result) {
				vAddFriendButton.setText("Friend request sent");
				vAddFriendButton.setEnabled(false);
				vAddFriendButton.setBackgroundColor(Color.parseColor("#00000000"));
				vAddFriendButton.setTextColor(getResources().getColor(R.color.dark_brown));
			} else {
				Toast.makeText(getApplicationContext(), "Error: Couldn't submit to server", 
						Toast.LENGTH_SHORT).show();
			}
		}

	}

	private class ApproveFriendTask extends AsyncTask<Integer, Void, Boolean> {
		private User mUser;
		@Override
		protected Boolean doInBackground(Integer... id) {
			int myId = id[0];
			int otherId = id[1];

			if(approveFriend(myId, otherId)) {
				mUser = DataFetcher.fetchUser(otherId, myId, mAuth);
				if(mUser == null) {
					return false;
				} else {
					mNewsList = DataFetcher.fetchOwnNews(otherId, myId, mAuth);
					if(mNewsList == null) {
						return false;
					}
					return true;
				}
			}
			return false;
		}

		@Override
		protected void onPostExecute(Boolean result) {
			if(result) {
				mNewsAdapter = new NewsListAdapter(mContext,
						R.layout.news_entry, R.id.name, mNewsList, mInflater);
				vNewsList = (ListView) findViewById(R.id.news_list);
				vNewsList.setAdapter(mNewsAdapter);

				setupView();
			} else {
				Toast.makeText(getApplicationContext(), "Error: Couldn't submit to server", 
						Toast.LENGTH_SHORT).show();
			}
		}

	}

	public void setupView() {
		vSwitcher.showNext();
		vName.setText(mUser.name);
		vImage.setImageUrl(mUser.imageUrl);
		vImage.loadImage();
		
		Log.i(TAG, "Last check-in id = " + mUser.lastCheckin);
		if(mUser.lastCheckin != 0) {
			vLastCheckinLabel.setVisibility(View.VISIBLE);
			vLastCheckin.setVisibility(View.VISIBLE);
			vLastCheckin.setText(mUser.placeName);
			vLastCheckin.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					Intent i = new Intent(UserActivity.this, PlaceActivity.class);
					i.putExtra("id", mUser.placeId);
					startActivity(i);
				}
			});
		}

		vWantedlistButton = (Button) findViewById(R.id.wantedlist_btn);
		vWantedlistButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent i = new Intent(mContext, WantedBrowseActivity.class);
				i.putExtra("id", mUser.id);
				startActivity(i);
			}

		});
		
		vFriendslistButton = (Button) findViewById(R.id.friendlist_btn);
		vFriendslistButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent i = new Intent(mContext, FriendBrowseActivity.class);
				i.putExtra("id", mUser.id);
				startActivity(i);
			}

		});

		if(mUser.id == mSharedPref.getInt(Main.USER_ID, 0)) {
			vChatButton = (Button) findViewById(R.id.chat_btn);
			vChatButton.setVisibility(View.INVISIBLE);
			return;
		}

		vChatButton = (Button) findViewById(R.id.chat_btn);
		vChatButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if(isOnline) {
					Intent i = new Intent(mContext, ChatActivity.class);
					i.putExtra("id", mUser.id);
					i.putExtra("name", mUser.name);
					startActivity(i);
				} else {
					Toast.makeText(getApplicationContext(), "Error: User is not online now", 
							Toast.LENGTH_SHORT).show();
				}

			}
		});
	}

	private BroadcastReceiver mChatStatusReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			Boolean status = intent.getBooleanExtra("status", false);
			if(status) {
				isOnline = true;
				vOnlineStatus.setText("online");
				vOnlineStatus.setTextColor(getResources().getColor(R.color.green));
			} else {
				isOnline = false;
				vOnlineStatus.setText("offline");
				vOnlineStatus.setTextColor(getResources().getColor(R.color.red));
			}
		}
	};

}
